package com.mini.grpc.loadbalance;

import java.net.SocketAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

/**
 * 负载均衡器注册表
 * 管理负载均衡器提供者的注册和查找
 * 
 * @author Mini-gRPC
 */
public final class LoadBalancerRegistry {
    
    private static final Logger logger = Logger.getLogger(LoadBalancerRegistry.class.getName());
    
    private static final LoadBalancerRegistry INSTANCE = new LoadBalancerRegistry();
    
    private final Map<String, LoadBalancerProvider> providers = new ConcurrentHashMap<>();
    
    /**
     * 私有构造函数，单例模式
     */
    private LoadBalancerRegistry() {
        // 注册默认的负载均衡器提供者
        register(new RoundRobinLoadBalancerProvider());
        register(new PickFirstLoadBalancerProvider());
    }
    
    /**
     * 获取注册表实例
     * 
     * @return 注册表实例
     */
    public static LoadBalancerRegistry getInstance() {
        return INSTANCE;
    }
    
    /**
     * 注册负载均衡器提供者
     * 
     * @param provider 负载均衡器提供者
     */
    public void register(LoadBalancerProvider provider) {
        if (provider == null) {
            throw new IllegalArgumentException("provider cannot be null");
        }
        
        String name = provider.getName();
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("provider name cannot be null or empty");
        }
        
        providers.put(name, provider);
        logger.info("Registered load balancer provider: " + name);
    }
    
    /**
     * 注销负载均衡器提供者
     * 
     * @param name 负载均衡器名称
     */
    public void unregister(String name) {
        if (name != null) {
            LoadBalancerProvider removed = providers.remove(name);
            if (removed != null) {
                logger.info("Unregistered load balancer provider: " + name);
            }
        }
    }
    
    /**
     * 获取负载均衡器提供者
     * 
     * @param name 负载均衡器名称
     * @return 负载均衡器提供者，如果不存在返回null
     */
    public LoadBalancerProvider getProvider(String name) {
        return providers.get(name);
    }
    
    /**
     * 创建负载均衡器
     * 
     * @param name 负载均衡器名称
     * @return 负载均衡器实例，如果提供者不存在返回null
     */
    public LoadBalancer newLoadBalancer(String name) {
        LoadBalancerProvider provider = getProvider(name);
        return provider != null ? provider.newLoadBalancer() : null;
    }
    
    /**
     * 创建负载均衡器并初始化地址列表
     * 
     * @param name 负载均衡器名称
     * @param addresses 初始地址列表
     * @return 负载均衡器实例，如果提供者不存在返回null
     */
    public LoadBalancer newLoadBalancer(String name, List<SocketAddress> addresses) {
        LoadBalancerProvider provider = getProvider(name);
        return provider != null ? provider.newLoadBalancer(addresses) : null;
    }
    
    /**
     * 获取默认的负载均衡器（轮询）
     * 
     * @return 默认负载均衡器实例
     */
    public LoadBalancer getDefaultLoadBalancer() {
        return newLoadBalancer("round_robin");
    }
    
    /**
     * 获取默认的负载均衡器并初始化地址列表
     * 
     * @param addresses 初始地址列表
     * @return 默认负载均衡器实例
     */
    public LoadBalancer getDefaultLoadBalancer(List<SocketAddress> addresses) {
        return newLoadBalancer("round_robin", addresses);
    }
    
    /**
     * 轮询负载均衡器提供者
     */
    private static class RoundRobinLoadBalancerProvider implements LoadBalancerProvider {
        
        @Override
        public String getName() {
            return "round_robin";
        }
        
        @Override
        public LoadBalancer newLoadBalancer() {
            return new RoundRobinLoadBalancer();
        }
        
        @Override
        public LoadBalancer newLoadBalancer(List<SocketAddress> addresses) {
            return new RoundRobinLoadBalancer(addresses);
        }
        
        @Override
        public boolean isAvailable() {
            return true;
        }
        
        @Override
        public int getPriority() {
            return 5;
        }
    }
    
    /**
     * 选择第一个负载均衡器提供者
     */
    private static class PickFirstLoadBalancerProvider implements LoadBalancerProvider {
        
        @Override
        public String getName() {
            return "pick_first";
        }
        
        @Override
        public LoadBalancer newLoadBalancer() {
            return new PickFirstLoadBalancer();
        }
        
        @Override
        public LoadBalancer newLoadBalancer(List<SocketAddress> addresses) {
            return new PickFirstLoadBalancer(addresses);
        }
        
        @Override
        public boolean isAvailable() {
            return true;
        }
        
        @Override
        public int getPriority() {
            return 10;
        }
    }
} 